package com.zyl.blog.processing.manager;

import com.zyl.blog.common.domain.file.bean.FileStorage;
import com.zyl.blog.common.utils.Extreme.LogUtil;
import com.zyl.blog.processing.exception.FileProcessingException;
import com.zyl.blog.processing.processor.FileProcessor;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件处理器管理器
 * 统一管理所有文件处理器，提供处理器选择和调度功能
 * 
 * @author FinalFantasy
 * @version v1.0
 * @date 2025/09/01
 */
@Component
@RequiredArgsConstructor
public class FileProcessorManager {

    private final List<FileProcessor> fileProcessors;
    
    // 文件类型到处理器的映射
    private final Map<String, FileProcessor> processorMap = new HashMap<>();
    
    @PostConstruct
    public void initProcessorMap() {
        for (FileProcessor processor : fileProcessors) {
            for (String supportedType : processor.getSupportedTypes()) {
                processorMap.put(supportedType.toLowerCase(), processor);
                LogUtil.info("注册文件处理器: {} -> {}", supportedType, processor.getProcessorName());
            }
        }
        
        LogUtil.info("文件处理器初始化完成，共注册 {} 个处理器，支持 {} 种文件类型", 
                    fileProcessors.size(), processorMap.size());
    }

    /**
     * 根据文件类型获取处理器
     * @param fileType 文件类型
     * @return 对应的处理器，如果不支持返回null
     */
    public FileProcessor getProcessor(String fileType) {
        if (fileType == null) {
            return null;
        }
        return processorMap.get(fileType.toLowerCase());
    }

    /**
     * 检查是否支持指定文件类型
     * @param fileType 文件类型
     * @return 是否支持
     */
    public boolean isSupported(String fileType) {
        return getProcessor(fileType) != null;
    }

    /**
     * 获取所有支持的文件类型
     * @return 支持的文件类型列表
     */
    public List<String> getSupportedFileTypes() {
        return new ArrayList<>(processorMap.keySet());
    }

    /**
     * 获取处理器统计信息
     * @return 处理器信息映射
     */
    public Map<String, Object> getProcessorStatistics() {
        Map<String, Object> stats = new HashMap<>();
        
        stats.put("totalProcessors", fileProcessors.size());
        stats.put("supportedTypes", processorMap.keySet());
        
        // 按处理器分组统计
        Map<String, List<String>> processorTypes = new HashMap<>();
        for (FileProcessor processor : fileProcessors) {
            processorTypes.put(processor.getProcessorName(), processor.getSupportedTypes());
        }
        stats.put("processorDetails", processorTypes);
        
        return stats;
    }

    /**
     * 提取文件文本内容（自动选择处理器）
     * @param file 文件
     * @return 提取的文本内容
     */
    public String extractText(MultipartFile file) {
        String fileType = getFileType(file);
        FileProcessor processor = getProcessor(fileType);
        
        if (processor == null) {
            throw new FileProcessingException("不支持的文件类型: " + fileType);
        }
        
        LogUtil.info("使用 {} 提取文件文本: {}", processor.getProcessorName(), file.getOriginalFilename());
        return processor.extractText(file);
    }

    /**
     * 提取文件文本内容（基于存储文件）
     * @param fileStorage 文件存储信息
     * @return 提取的文本内容
     */
    public String extractText(FileStorage fileStorage) {
        FileProcessor processor = getProcessor(fileStorage.getFileType());
        
        if (processor == null) {
            throw new FileProcessingException("不支持的文件类型: " + fileStorage.getFileType());
        }
        
        LogUtil.info("使用 {} 提取文件文本: {}", processor.getProcessorName(), fileStorage.getOriginalFileName());
        return processor.extractText(fileStorage);
    }

    /**
     * 提取文件元数据（自动选择处理器）
     * @param file 文件
     * @return 元数据信息
     */
    public Map<String, Object> extractMetadata(MultipartFile file) {
        String fileType = getFileType(file);
        FileProcessor processor = getProcessor(fileType);
        
        if (processor == null) {
            throw new FileProcessingException("不支持的文件类型: " + fileType);
        }
        
        LogUtil.info("使用 {} 提取文件元数据: {}", processor.getProcessorName(), file.getOriginalFilename());
        return processor.extractMetadata(file);
    }

    /**
     * 提取文件元数据（基于存储文件）
     * @param fileStorage 文件存储信息
     * @return 元数据信息
     */
    public Map<String, Object> extractMetadata(FileStorage fileStorage) {
        FileProcessor processor = getProcessor(fileStorage.getFileType());
        
        if (processor == null) {
            throw new FileProcessingException("不支持的文件类型: " + fileStorage.getFileType());
        }
        
        LogUtil.info("使用 {} 提取文件元数据: {}", processor.getProcessorName(), fileStorage.getOriginalFileName());
        return processor.extractMetadata(fileStorage);
    }

    /**
     * 验证文件格式（自动选择处理器）
     * @param file 文件
     * @return 验证结果
     */
    public boolean validateFormat(MultipartFile file) {
        String fileType = getFileType(file);
        FileProcessor processor = getProcessor(fileType);
        
        if (processor == null) {
            LogUtil.warn("文件类型不支持: {}", fileType);
            return false;
        }
        
        boolean isValid = processor.validateFormat(file);
        LogUtil.info("文件格式验证 {}: {} ({})", 
                    isValid ? "通过" : "失败", 
                    file.getOriginalFilename(), 
                    processor.getProcessorName());
        return isValid;
    }

    /**
     * 生成文件预览（基于存储文件）
     * @param fileStorage 文件存储信息
     * @return 预览信息
     */
    public Map<String, Object> generatePreview(FileStorage fileStorage) {
        FileProcessor processor = getProcessor(fileStorage.getFileType());
        
        if (processor == null) {
            throw new FileProcessingException("不支持的文件类型: " + fileStorage.getFileType());
        }
        
        LogUtil.info("使用 {} 生成文件预览: {}", processor.getProcessorName(), fileStorage.getOriginalFileName());
        return processor.generatePreview(fileStorage);
    }

    /**
     * 批量处理文件
     * @param files 文件列表
     * @param operation 操作类型（text, metadata, validate等）
     * @return 处理结果
     */
    public Map<String, Object> batchProcess(List<MultipartFile> files, String operation) {
        Map<String, Object> results = new HashMap<>();
        Map<String, Object> errors = new HashMap<>();
        
        for (int i = 0; i < files.size(); i++) {
            MultipartFile file = files.get(i);
            String key = "file_" + i + "_" + file.getOriginalFilename();
            
            try {
                Object result = switch (operation.toLowerCase()) {
                    case "text" -> extractText(file);
                    case "metadata" -> extractMetadata(file);
                    case "validate" -> validateFormat(file);
                    default -> throw new IllegalArgumentException("不支持的操作: " + operation);
                };
                
                results.put(key, result);
                
            } catch (Exception e) {
                LogUtil.error("批量处理文件失败: {}", e, file.getOriginalFilename());
                errors.put(key, e.getMessage());
            }
        }
        
        Map<String, Object> response = new HashMap<>();
        response.put("success", results);
        response.put("errors", errors);
        response.put("totalFiles", files.size());
        response.put("successCount", results.size());
        response.put("errorCount", errors.size());
        
        return response;
    }

    /**
     * 获取文件类型（从文件名提取扩展名）
     */
    private String getFileType(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        return com.zyl.blog.processing.util.FileProcessingUtils.getFileExtension(fileName);
    }

    /**
     * 获取文件类型的详细信息
     * @param fileType 文件类型
     * @return 类型详细信息
     */
    public Map<String, Object> getFileTypeInfo(String fileType) {
        FileProcessor processor = getProcessor(fileType);
        if (processor == null) {
            return Map.of("supported", false, "fileType", fileType);
        }
        
        return Map.of(
            "supported", true,
            "fileType", fileType,
            "processorName", processor.getProcessorName(),
            "supportedTypes", processor.getSupportedTypes()
        );
    }
}